package com.core.coder;

import java.security.PrivateKey;

import javax.crypto.SecretKey;

import org.apache.log4j.Logger;

/**
 * 授权（authoKey）、加密（RSA+AES）
 * @author longrm
 * @date 2013-11-15
 */
public class GameCoder {

	public static final String splitStr = "_";
	public static final String charsetName = "UTF-8";

	private String gameName;
	private String areaName;

	private static PrivateKey rsaKey;
	private SecretKey aesKey;

	public GameCoder() {
		this.gameName = Constant.GAME_NAME;
		this.areaName = Constant.AREA_NAME;
		String key = gameName + splitStr + areaName;
		// 创建rsa key
		if (rsaKey == null) {
			try {
				rsaKey = BaseCoder.generateRSAPrivateKey(Constant.RSA_PRIVATE_KEY);
				Logger.getRootLogger().info("创建RSA密钥（" + key + "）");
			} catch (Exception e) {
				e.printStackTrace();
				Logger.getRootLogger().error("创建RSA密钥（" + key + "）失败", e);
			}
		}
	}

	public String getGameName() {
		return gameName;
	}

	public void setGameName(String gameName) {
		this.gameName = gameName;
	}

	public String getAreaName() {
		return areaName;
	}

	public void setAreaName(String areaName) {
		this.areaName = areaName;
	}

	/**
	 * 创建授权authoKey，生成随机AES密钥
	 * @return 团队_游戏名_游戏服务器_随机AES密钥_时间串
	 * @throws Exception
	 */
	public String createAuthoKey() throws Exception {
		String authoKey = Constant.TEAM + splitStr + gameName + splitStr + areaName;
		if (rsaKey != null) {
			// 生成随机AES密钥
			String aesSeed = StringUtil.randomString(16);
			aesKey = BaseCoder.generateSecretKey("AES", 128, aesSeed);
			// authoKey
			authoKey += splitStr + aesSeed + splitStr + System.currentTimeMillis();
			byte[] bytes = BaseCoder.encrypt(authoKey.getBytes(charsetName), "RSA", rsaKey);
			return BaseCoder.encodeBASE64(bytes);
		} else
			// TODO throw exception
			return authoKey;
	}

	/**
	 * 授权：判断请求是否合法可靠
	 * @param authoKey
	 * @return
	 * @throws Exception
	 */
	public boolean authorize(String authoKey) throws Exception {
		// step one：使用rsaKey解密authoKey
		if (rsaKey != null) {
			byte[] bytes = BaseCoder.decodeBASE64(authoKey);
			byte[] data = BaseCoder.decrypt(bytes, "RSA", rsaKey);
			authoKey = new String(data, charsetName);
		}

		// step two：判断各个要素是否合法
		String[] strs = authoKey.split(splitStr);
		if (rsaKey != null && strs.length != 5)
			return false;
		else if (rsaKey == null && strs.length != 3)
			return false;

		if (!Constant.TEAM.equals(strs[0]) || !gameName.equals(strs[1]) || !areaName.equals(strs[2]))
			return false;

		// step three：解析出aesKey
		String aesSeed = rsaKey != null ? strs[3] : null;
		aesKey = BaseCoder.generateSecretKey("AES", 128, aesSeed);
		return true;
	}

	public String encrypt(Object data) throws Exception {
		return encrypt(data.toString());
	}

	/**
	 * 加密
	 * @param text
	 * @return
	 * @throws Exception
	 */
	public String encrypt(String text) throws Exception {
		if (aesKey != null) {
			byte[] bytes = BaseCoder.encrypt(text.getBytes(charsetName), "AES", aesKey);
			return BaseCoder.encodeBASE64(bytes);
		} else
			// TODO throw exception
			return text;
	}

	/**
	 * 解密
	 * @param text
	 * @return
	 * @throws Exception
	 */
	public String decrypt(String text) throws Exception {
		if (aesKey != null) {
			byte[] bytes = BaseCoder.decodeBASE64(text);
			byte[] data = BaseCoder.decrypt(bytes, "AES", aesKey);
			return new String(data, charsetName);
		} else
			// TODO throw exception
			return text;
	}

}
